import { Injectable, Inject } from "@angular/core";
import { Router } from "@angular/router";
import { Actions, Effect, ofType } from "@ngrx/effects";
import { of } from "rxjs";
import { catchError, exhaustMap, tap } from "rxjs/operators";
import {
  ILoginRequest,
  ILoginResponse,
  IEnrollRequest,
  IEnrollResponse,
  IFindUserResponse,
  ISavePwdResponse,
  ISavePwdRequest,
  ILogoutResponse
} from "@/user/store/models/user";
import { LoginComponent } from "../../cpt/login/login.component";

import { Store, select } from "@ngrx/store";
import * as fromUser from "@/user/store/reducers/index";
import { map, filter } from "rxjs/operators";
import { Subscription } from "rxjs";
import { UserActions } from "@/user/store/actions";
import { combineAll, debounceTime } from "rxjs/operators";

@Injectable()
export class UserEffects {
  constructor(
    private actions$: Actions,
    @Inject("ConfigService") private configService,
    @Inject("UserService") private userService,
    @Inject("MsgService") private msgService,
    private router: Router,
    private store: Store<fromUser.State>
  ) {}

  @Effect()
  enroll$ = this.actions$.pipe(
    ofType<UserActions.Enroll>(UserActions.UserActionTypes.Enroll),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.userService.enroll(payload.req).pipe(
        map((res: IEnrollResponse) => {
          return new UserActions.EnrollSuccess({ res, cpt: payload.cpt });
        }),
        catchError(error => of(new UserActions.EnrollError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  enrollSuccess$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.EnrollSuccess),
    tap((response: any) => {
      const { payload } = response;
      payload.cpt.sliderCodeRef.initCode();
      if (200 === payload.res.code) {
        this.msgService.success("success");
        this.router.navigate(["u", "login"]);
      } else {
        this.msgService.error("error");
      }
    })
  );

  @Effect({ dispatch: false })
  enrollError$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.EnrollError),
    tap(() => {
      this.msgService.error("error");
    })
  );

  @Effect()
  login$ = this.actions$.pipe(
    ofType<UserActions.Login>(UserActions.UserActionTypes.Login),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.userService.login(payload.req).pipe(
        map(
          (res: ILoginResponse) =>
            new UserActions.LoginSuccess({ res, cpt: payload.cpt })
        ),
        catchError(error => of(new UserActions.LoginError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  loginSuccess$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.LoginSuccess),
    tap((response: any) => {
      const { payload } = response;
      // 必须触发路由才会 call user 所以 直接路由跳转就行了 拦截交给 auth guard 来做

      if (200 === payload.res.code) {
        this.router.navigate(["main", "home"], {
          queryParams: {
            symbol: `${this.configService.defQuerySymbol.zi}_${
              this.configService.defQuerySymbol.mu
            }`
          }
        });
        // this.msgService.success("success");
      } else {
        this.msgService.error("error");
        // payload.cpt.validateForm.reset();
        payload.cpt.sliderCodeRef.initCode();
      }
    })
  );

  @Effect({ dispatch: false })
  loginError$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.LoginError),
    tap(() => {
      // do something
      this.msgService.error("data error");
    })
  );

  @Effect()
  logout$ = this.actions$.pipe(
    ofType<UserActions.Logout>(UserActions.UserActionTypes.Logout),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.userService.logout(payload.req).pipe(
        map(
          (res: ILogoutResponse) =>
            new UserActions.LogoutSuccess({ res, cpt: payload.cpt })
        ),
        catchError(error => of(new UserActions.LogoutError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  logoutSuccess$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.LogoutSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        // this.msgService.success("success");
        this.router.navigate(["u/login"]);
        // this.store.dispatch(new UserActions.FindUser({ req: undefined }));
      } else {
        this.msgService.error("error");
        // payload.cpt.sliderCodeRef.initCode();
        payload.cpt.validateForm.reset();
      }
    })
  );

  @Effect({ dispatch: false })
  logoutError$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.LogoutError),
    tap(() => {
      // do something
      this.msgService.error("data error");
    })
  );

  @Effect()
  findUser$ = this.actions$.pipe(
    ofType<UserActions.FindUser>(UserActions.UserActionTypes.FindUser),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.userService.find().pipe(
        map(
          (res: IFindUserResponse) => new UserActions.FindUserSuccess({ res })
        ),
        catchError(error => of(new UserActions.FindUserError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  findUserSuccess$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.FindUserSuccess),
    tap((response: any) => {})
  );

  @Effect({ dispatch: false })
  findUserError$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.FindUserError),
    tap(() => {
      // do something
      this.msgService.error("data error");
    })
  );

  @Effect()
  savePwd$ = this.actions$.pipe(
    ofType<UserActions.SavePwd>(UserActions.UserActionTypes.SavePwd),
    map(action => action.payload),
    exhaustMap(payload => {
      return this.userService.savePwd(payload.req).pipe(
        map(
          (res: ISavePwdResponse) =>
            new UserActions.SavePwdSuccess({ res, cpt: payload.cpt })
        ),
        catchError(error => of(new UserActions.SavePwdError({ error })))
      );
    })
  );

  @Effect({ dispatch: false })
  savePwdSuccess$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.SavePwdSuccess),
    tap((response: any) => {
      const { payload } = response;
      if (200 === payload.res.code) {
        this.msgService.success("success");
        this.router.navigate(["u", "login"]);
      } else {
        this.msgService.error("error");
        payload.cpt.sliderCodeRef.initCode();
      }
    })
  );

  @Effect({ dispatch: false })
  savePwdError$ = this.actions$.pipe(
    ofType(UserActions.UserActionTypes.SavePwdError),
    tap(() => {
      // do something
      this.msgService.error("data error");
    })
  );
}
